home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i023: cpp - a c preprocessor with some ANSI features, Part02/05
- Message-ID: <11031@xanth.cs.odu.edu>
- Date: 18 Jan 90 00:18:29 GMT
- Sender: tadguy@cs.odu.edu
- Reply-To: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
- Lines: 1503
- Approved: tadguy@cs.odu.edu (Tad Guy)
-
- Submitted-by: Olaf 'Rhialto' Seibert <U211344@HNYKUN11.BITNET>
- Posting-number: Volume 90, Issue 023
- Archive-name: unix/cpp/part02
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 5)."
- # Contents: Cpp2.c Cpp3.c org/cpp.mem
- # Wrapped by tadguy@xanth on Wed Jan 17 19:17:33 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Cpp2.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Cpp2.c'\"
- else
- echo shar: Extracting \"'Cpp2.c'\" \(17735 characters\)
- sed "s/^X//" >'Cpp2.c' <<'END_OF_FILE'
- X/*
- X * C P P 2 . C
- X *
- X * Process #control lines
- X *
- X * Edit history
- X * 13-Nov-84 MM Split from cpp1.c
- X * 21-Oct-85 RMS Do not turn on `instring' while reading #include arg.
- X * Rename `token' to `tokenbuf'.
- X * Flush tabs at end of #include line, like spaces.
- X * 14-Mar-86 FNF Incorporate macro based C debugging package.
- X * Port to Commodore AMIGA.
- X * 25-May-86 FNF Change handling of fully qualified include file
- X * pathnames (like "/usr/include/stdio.h" for unix,
- X * or "df0:include/stdio.h" for the Amiga) to be
- X * used verbatum in the first open attempt.
- X * 20-Aug-88 Ois Added #error. Passed unrecognized # commands.
- X * Added \n when those lines are passed.
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "cppdef.h"
- X#include "cpp.h"
- X#if HOST == SYS_VMS
- X/*
- X * Include the rms stuff. (We can't just include rms.h as it uses the
- X * VaxC-specific library include syntax that Decus CPP doesn't support.
- X * By including things by hand, we can CPP ourself.)
- X */
- X#include <nam.h>
- X#include <fab.h>
- X#include <rab.h>
- X#include <rmsdef.h>
- X#endif
- X
- X/*
- X * Generate (by hand-inspection) a set of unique values for each control
- X * operator. Note that this is not guaranteed to work for non-Ascii
- X * machines. CPP won't compile if there are hash conflicts.
- X */
- X
- X#define L_assert ('a' + ('s' << 1))
- X#define L_define ('d' + ('f' << 1))
- X#define L_elif ('e' + ('i' << 1))
- X#define L_else ('e' + ('s' << 1))
- X#define L_endif ('e' + ('d' << 1))
- X#define L_error ('e' + ('r' << 1))
- X#define L_if ('i' + (EOS << 1))
- X#define L_ifdef ('i' + ('d' << 1))
- X#define L_ifndef ('i' + ('n' << 1))
- X#define L_include ('i' + ('c' << 1))
- X#define L_line ('l' + ('n' << 1))
- X#define L_nogood (EOS + (EOS << 1)) /* To catch #i */
- X#define L_pragma ('p' + ('a' << 1))
- X#define L_undef ('u' + ('d' << 1))
- X#if DEBUG
- X#define L_debug ('d' + ('b' << 1)) /* #debug */
- X#define L_nodebug ('n' + ('d' << 1)) /* #nodebug */
- X#endif
- X
- Xint
- Xcontrol(counter)
- Xint counter; /* Pending newline counter */
- X/*
- X * Process #control lines. Simple commands are processed inline,
- X * while complex commands have their own subroutines.
- X *
- X * The counter is used to force out a newline before #line, and
- X * #pragma commands. This prevents these commands from ending up at
- X * the end of the previous line if cpp is invoked with the -C option.
- X */
- X{
- X register int c;
- X register char *tp;
- X register int hash;
- X char *ep;
- X
- X DBUG_ENTER ("control");
- X c = skipws();
- X if (c == '\n' || c == EOF_CHAR)
- X DBUG_RETURN (counter + 1);
- X if (!isdigit(c))
- X scanid(c); /* Get #word to tokenbuf */
- X else {
- X unget(); /* Hack -- allow #123 as a */
- X strcpy(tokenbuf, "line"); /* synonym for #line 123 */
- X }
- X hash = (tokenbuf[1] == EOS) ? L_nogood : (tokenbuf[0] + (tokenbuf[2] << 1));
- X switch (hash) {
- X case L_assert: tp = "assert"; break;
- X case L_define: tp = "define"; break;
- X case L_elif: tp = "elif"; break;
- X case L_else: tp = "else"; break;
- X case L_endif: tp = "endif"; break;
- X case L_error: tp = "error"; break;
- X case L_if: tp = "if"; break;
- X case L_ifdef: tp = "ifdef"; break;
- X case L_ifndef: tp = "ifndef"; break;
- X case L_include: tp = "include"; break;
- X case L_line: tp = "line"; break;
- X case L_pragma: tp = "pragma"; break;
- X case L_undef: tp = "undef"; break;
- X#if DEBUG
- X case L_debug: tp = "debug"; break;
- X case L_nodebug: tp = "nodebug"; break;
- X#endif
- X default: hash = L_nogood;
- X case L_nogood: tp = ""; break;
- X }
- X if (!streq(tp, tokenbuf))
- X hash = L_nogood;
- X /*
- X * hash is set to a unique value corresponding to the
- X * control keyword (or L_nogood if we think it's nonsense).
- X */
- X if (infile->fp == NULL)
- X cwarn("Control line \"%s\" within macro expansion", tokenbuf);
- X if (!compiling) { /* Not compiling now */
- X switch (hash) {
- X case L_if: /* These can't turn */
- X case L_ifdef: /* compilation on, but */
- X case L_ifndef: /* we must nest #if's */
- X if (++ifptr >= &ifstack[BLK_NEST])
- X goto if_nest_err;
- X *ifptr = 0; /* !WAS_COMPILING */
- X case L_line: /* Many */
- X /*
- X * Are pragma's always processed?
- X */
- X case L_pragma: /* options */
- X case L_include: /* are uninteresting */
- X case L_define: /* if we */
- X case L_undef: /* aren't */
- X case L_assert: /* compiling. */
- X case L_error:
- Xdump_line: skipnl(); /* Ignore rest of line */
- X DBUG_RETURN (counter + 1);
- X }
- X }
- X /*
- X * Make sure that #line and #pragma are output on a fresh line.
- X */
- X if (counter > 0 && (hash == L_line || hash == L_pragma)) {
- X putchar('\n');
- X counter--;
- X }
- X switch (hash) {
- X case L_line:
- X /*
- X * Parse the line to update the line number and "progname"
- X * field and line number for the next input line.
- X * Set wrongline to force it out later.
- X */
- X c = skipws();
- X workp = work; /* Save name in work */
- X while (c != '\n' && c != EOF_CHAR) {
- X save(c);
- X c = get();
- X }
- X unget();
- X save(EOS);
- X /*
- X * Split #line argument into <line-number> and <name>
- X * We subtract 1 as we want the number of the next line.
- X */
- X line = atoi(work) - 1; /* Reset line number */
- X for (tp = work; isdigit(*tp) || type[*tp] == SPA; tp++)
- X ; /* Skip over digits */
- X if (*tp != EOS) { /* Got a filename, so: */
- X if (*tp == '"' && (ep = strrchr(tp + 1, '"')) != NULL) {
- X tp++; /* Skip over left quote */
- X *ep = EOS; /* And ignore right one */
- X }
- X if (infile->progname != NULL) /* Give up the old name */
- X free(infile->progname); /* if it's allocated. */
- X infile->progname = savestring(tp);
- X }
- X wrongline = TRUE; /* Force output later */
- X break;
- X
- X case L_include:
- X doinclude();
- X break;
- X
- X case L_define:
- X dodefine();
- X break;
- X
- X case L_undef:
- X doundef();
- X break;
- X
- X case L_else:
- X if (ifptr == &ifstack[0])
- X goto nest_err;
- X else if ((*ifptr & ELSE_SEEN) != 0)
- X goto else_seen_err;
- X *ifptr |= ELSE_SEEN;
- X if ((*ifptr & WAS_COMPILING) != 0) {
- X if (compiling || (*ifptr & TRUE_SEEN) != 0)
- X compiling = FALSE;
- X else {
- X compiling = TRUE;
- X }
- X }
- X break;
- X
- X case L_elif:
- X if (ifptr == &ifstack[0])
- X goto nest_err;
- X else if ((*ifptr & ELSE_SEEN) != 0) {
- Xelse_seen_err: cerror("#%s may not follow #else", tokenbuf);
- X goto dump_line;
- X }
- X if ((*ifptr & (WAS_COMPILING | TRUE_SEEN)) != WAS_COMPILING) {
- X compiling = FALSE; /* Done compiling stuff */
- X goto dump_line; /* Skip this clause */
- X }
- X doif(L_if);
- X break;
- X
- X case L_error:
- X cerror("#error directive encountered", NULLST);
- X break;
- X
- X case L_if:
- X case L_ifdef:
- X case L_ifndef:
- X if (++ifptr >= &ifstack[BLK_NEST])
- Xif_nest_err: cfatal("Too many nested #%s statements", tokenbuf);
- X *ifptr = WAS_COMPILING;
- X doif(hash);
- X break;
- X
- X case L_endif:
- X if (ifptr == &ifstack[0]) {
- Xnest_err: cerror("#%s must be in an #if", tokenbuf);
- X goto dump_line;
- X }
- X if (!compiling && (*ifptr & WAS_COMPILING) != 0)
- X wrongline = TRUE;
- X compiling = ((*ifptr & WAS_COMPILING) != 0);
- X --ifptr;
- X break;
- X
- X case L_assert:
- X if (eval() == 0)
- X cerror("Preprocessor assertion failure", NULLST);
- X break;
- X
- X case L_pragma:
- X /*
- X * #pragma is provided to pass "options" to later
- X * passes of the compiler. cpp doesn't have any yet.
- X */
- X printf("#pragma ");
- Xpass_line:
- X while ((c = get()) != '\n' && c != EOF_CHAR)
- X cput(c);
- X unget();
- X cput('\n');
- X break;
- X
- X#if DEBUG
- X case L_debug:
- X if (debug == 0)
- X dumpdef("debug set on");
- X debug++;
- X break;
- X
- X case L_nodebug:
- X debug--;
- X break;
- X#endif
- X
- X default:
- X /*
- X * Undefined #control keyword.
- X * Note: the correct behavior may be to warn and
- X * pass the line to a subsequent compiler pass.
- X * This would allow #asm or similar extensions.
- X */
- X /* cerror("Illegal # command \"%s\"", tokenbuf); */
- X printf("#%s ", tokenbuf);
- X goto pass_line;
- X break;
- X }
- X if (hash != L_include) {
- X#if OLD_PREPROCESSOR
- X /*
- X * Ignore the rest of the #control line so you can write
- X * #if foo
- X * #endif foo
- X */
- X goto dump_line; /* Take common exit */
- X#else
- X if (skipws() != '\n') {
- X cwarn("Unexpected text in #control line ignored", NULLST);
- X skipnl();
- X }
- X#endif
- X }
- X DBUG_RETURN (counter + 1);
- X}
- X
- XFILE_LOCAL
- Xdoif(hash)
- Xint hash;
- X/*
- X * Process an #if, #ifdef, or #ifndef. The latter two are straightforward,
- X * while #if needs a subroutine of its own to evaluate the expression.
- X *
- X * doif() is called only if compiling is TRUE. If false, compilation
- X * is always supressed, so we don't need to evaluate anything. This
- X * supresses unnecessary warnings.
- X */
- X{
- X register int c;
- X register int found;
- X
- X DBUG_ENTER ("doif");
- X if ((c = skipws()) == '\n' || c == EOF_CHAR) {
- X unget();
- X goto badif;
- X }
- X if (hash == L_if) {
- X unget();
- X found = (eval() != 0); /* Evaluate expr, != 0 is TRUE */
- X hash = L_ifdef; /* #if is now like #ifdef */
- X }
- X else {
- X if (type[c] != LET) /* Next non-blank isn't letter */
- X goto badif; /* ... is an error */
- X found = (lookid(c) != NULL); /* Look for it in symbol table */
- X }
- X if (found == (hash == L_ifdef)) {
- X compiling = TRUE;
- X *ifptr |= TRUE_SEEN;
- X }
- X else {
- X compiling = FALSE;
- X }
- X DBUG_VOID_RETURN;
- X
- Xbadif: cerror("#if, #ifdef, or #ifndef without an argument", NULLST);
- X#if !OLD_PREPROCESSOR
- X skipnl(); /* Prevent an extra */
- X unget(); /* Error message */
- X#endif
- X DBUG_VOID_RETURN;
- X}
- X
- XFILE_LOCAL
- Xdoinclude()
- X/*
- X * Process the #include control line.
- X * There are three variations:
- X * #include "file" search somewhere relative to the
- X * current source file, if not found,
- X * treat as #include <file>.
- X * #include <file> Search in an implementation-dependent
- X * list of places.
- X * #include token Expand the token, it must be one of
- X * "file" or <file>, process as such.
- X *
- X * Note: the November 12 draft forbids '>' in the #include <file> format.
- X * This restriction is unnecessary and not implemented.
- X */
- X{
- X register int c;
- X register int delim;
- X#if HOST == SYS_VMS
- X char def_filename[NAM$C_MAXRSS + 1];
- X#endif
- X
- X DBUG_ENTER ("doinclude");
- X delim = macroid(skipws());
- X if (delim != '<' && delim != '"')
- X goto incerr;
- X if (delim == '<')
- X delim = '>';
- X workp = work;
- X while ((c = get()) != '\n' && c != EOF_CHAR)
- X save(c); /* Put it away. */
- X unget(); /* Force nl after includee */
- X /*
- X * The draft is unclear if the following should be done.
- X */
- X while (--workp >= work && (*workp == ' ' || *workp == '\t'))
- X ; /* Trim blanks from filename */
- X if (*workp != delim)
- X goto incerr;
- X *workp = EOS; /* Terminate filename */
- X#if HOST == SYS_VMS
- X /*
- X * Assume the default .h filetype.
- X */
- X if (!vmsparse(work, ".H", def_filename)) {
- X perror(work); /* Oops. */
- X goto incerr;
- X }
- X else if (openinclude(def_filename, (delim == '"')))
- X DBUG_VOID_RETURN;
- X#else
- X if (openinclude(work, (delim == '"')))
- X DBUG_VOID_RETURN;
- X#endif
- X /*
- X * No sense continuing if #include file isn't there.
- X */
- X cfatal("Cannot open include file \"%s\"", work);
- X
- Xincerr: cerror("#include syntax error", NULLST);
- X DBUG_VOID_RETURN;
- X}
- X
- XFILE_LOCAL int
- Xopeninclude(filename, searchlocal)
- Xchar *filename; /* Input file name */
- Xint searchlocal; /* TRUE if #include "file" */
- X/*
- X * Actually open an include file. This routine is only called from
- X * doinclude() above, but was written as a separate subroutine for
- X * programmer convenience. It searches the list of directories
- X * and actually opens the file, linking it into the list of
- X * active files. Returns TRUE if the file was opened, FALSE
- X * if openinclude() fails. No error message is printed.
- X */
- X{
- X register char **incptr;
- X#if HOST == SYS_VMS
- X#if NWORK < (NAM$C_MAXRSS + 1)
- X << error, NWORK isn't greater than NAM$C_MAXRSS >>
- X#endif
- X#endif
- X char tmpname[NWORK]; /* Filename work area */
- X
- X DBUG_ENTER ("openinclude");
- X#if HOST == SYS_UNIX
- X if ((filename[0] == '/') && openfile(filename)) {
- X DBUG_RETURN (TRUE);
- X }
- X#endif
- X#if HOST == SYS_AMIGADOS
- X if ((strchr (filename, ':') != NULL) && openfile (filename)) {
- X DBUG_RETURN (TRUE);
- X }
- X#endif
- X if (searchlocal) {
- X /*
- X * Look in local directory first.
- X * Try to open filename relative to the directory of the current
- X * source file (as opposed to the current directory). (ARF, SCK).
- X * Note that the fully qualified pathname is always built by
- X * discarding the last pathname component of the source file
- X * name then tacking on the #include argument.
- X */
- X if(hasdirectory(infile->filename, tmpname)) {
- X strcat(tmpname, filename);
- X } else {
- X strcpy(tmpname, filename);
- X }
- X if (openfile(tmpname))
- X DBUG_RETURN (TRUE);
- X }
- X /*
- X * Look in any directories specified by -I command line
- X * arguments, then in the builtin search list.
- X */
- X for (incptr = incdir; incptr < incend; incptr++) {
- X if (strlen(*incptr) + strlen(filename) >= sizeof(tmpname)) {
- X cfatal("Filename work buffer overflow", NULLST);
- X } else {
- X#if HOST == SYS_UNIX /* Implied '/' */
- X sprintf(tmpname, "%s/%s", *incptr, filename);
- X#else
- X sprintf(tmpname, "%s%s", *incptr, filename);
- X#endif
- X if (openfile(tmpname))
- X DBUG_RETURN (TRUE);
- X }
- X }
- X DBUG_RETURN (FALSE);
- X}
- X
- XFILE_LOCAL int
- Xhasdirectory(source, result)
- Xchar *source; /* Directory to examine */
- Xchar *result; /* Put directory stuff here */
- X/*
- X * If a device or directory is found in the source filename string, the
- X * node/device/directory part of the string is copied to result and
- X * hasdirectory returns TRUE. Else, nothing is copied and it returns FALSE.
- X */
- X{
- X#if HOST == SYS_UNIX
- X register char *tp;
- X
- X DBUG_ENTER ("hasdirectory");
- X if ((tp = strrchr(source, '/')) == NULL)
- X DBUG_RETURN (FALSE);
- X else {
- X strncpy(result, source, tp - source + 1);
- X result[tp - source + 1] = EOS;
- X DBUG_RETURN (TRUE);
- X }
- X#elif HOST == SYS_AMIGADOS
- X register char *tp1, *tp2;
- X
- X DBUG_ENTER ("hasdirectory");
- X
- X if ((tp1 = strrchr(source, ':')) == NULL)
- X tp1 = source;
- X if ((tp2 = strrchr(tp1, '/')) == NULL)
- X tp2 = tp1;
- X
- X if (tp2 == source)
- X DBUG_RETURN (FALSE);
- X else {
- X strncpy(result, source, tp2 - source + 1);
- X result[tp2 - source + 1] = EOS;
- X DBUG_RETURN (TRUE);
- X }
- X#elif HOST == SYS_VMS
- X DBUG_ENTER ("hasdirectory");
- X if (vmsparse(source, NULLST, result)
- X && result[0] != EOS)
- X DBUG_RETURN (TRUE);
- X else {
- X DBUG_RETURN (FALSE);
- X }
- X#else
- X /*
- X * Random DEC operating system (RSX, RT11, RSTS/E)
- X */
- X register char *tp;
- X
- X DBUG_ENTER ("hasdirectory");
- X if ((tp = strrchr(source, ']')) == NULL
- X && (tp = strrchr(source, ':')) == NULL)
- X DBUG_RETURN (FALSE);
- X else {
- X strncpy(result, source, tp - source + 1);
- X result[tp - source + 1] = EOS;
- X DBUG_RETURN (TRUE);
- X }
- X#endif
- X}
- X
- X#if HOST == SYS_VMS
- X
- X/*
- X * EXP_DEV is set if a device was specified, EXP_DIR if a directory
- X * is specified. (Both set indicate a file-logical, but EXP_DEV
- X * would be set by itself if you are reading, say, SYS$INPUT:)
- X */
- X#define DEVDIR (NAM$M_EXP_DEV | NAM$M_EXP_DIR)
- X
- XFILE_LOCAL int
- Xvmsparse(source, defstring, result)
- Xchar *source;
- Xchar *defstring; /* non-NULL -> default string. */
- Xchar *result; /* Size is at least NAM$C_MAXRSS + 1 */
- X/*
- X * Parse the source string, applying the default (properly, using
- X * the system parse routine), storing it in result.
- X * TRUE if it parsed, FALSE on error.
- X *
- X * If defstring is NULL, there are no defaults and result gets
- X * (just) the node::[directory] part of the string (possibly "")
- X */
- X{
- X struct FAB fab = cc$rms_fab; /* File access block */
- X struct NAM nam = cc$rms_nam; /* File name block */
- X char fullname[NAM$C_MAXRSS + 1];
- X register char *rp; /* Result pointer */
- X
- X DBUG_ENTER ("vmsparse");
- X fab.fab$l_nam = &nam; /* fab -> nam */
- X fab.fab$l_fna = source; /* Source filename */
- X fab.fab$b_fns = strlen(source); /* Size of source */
- X fab.fab$l_dna = defstring; /* Default string */
- X if (defstring != NULLST)
- X fab.fab$b_dns = strlen(defstring); /* Size of default */
- X nam.nam$l_esa = fullname; /* Expanded filename */
- X nam.nam$b_ess = NAM$C_MAXRSS; /* Expanded name size */
- X if (sys$parse(&fab) == RMS$_NORMAL) { /* Parse away */
- X fullname[nam.nam$b_esl] = EOS; /* Terminate string */
- X result[0] = EOS; /* Just in case */
- X rp = &result[0];
- X /*
- X * Remove stuff added implicitly, accepting node names and
- X * dev:[directory] strings (but not process-permanent files).
- X */
- X if ((nam.nam$l_fnb & NAM$M_PPF) == 0) {
- X if ((nam.nam$l_fnb & NAM$M_NODE) != 0) {
- X strncpy(result, nam.nam$l_node, nam.nam$b_node);
- X rp += nam.nam$b_node;
- X *rp = EOS;
- X }
- X if ((nam.nam$l_fnb & DEVDIR) == DEVDIR) {
- X strncpy(rp, nam.nam$l_dev, nam.nam$b_dev + nam.nam$b_dir);
- X rp += nam.nam$b_dev + nam.nam$b_dir;
- X *rp = EOS;
- X }
- X }
- X if (defstring != NULLST) {
- X strncpy(rp, nam.nam$l_name, nam.nam$b_name + nam.nam$b_type);
- X rp += nam.nam$b_name + nam.nam$b_type;
- X *rp = EOS;
- X if ((nam.nam$l_fnb & NAM$M_EXP_VER) != 0) {
- X strncpy(rp, nam.nam$l_ver, nam.nam$b_ver);
- X rp[nam.nam$b_ver] = EOS;
- X }
- X }
- X DBUG_RETURN (TRUE);
- X }
- X DBUG_RETURN (FALSE);
- X}
- X#endif
- X
- END_OF_FILE
- if test 17735 -ne `wc -c <'Cpp2.c'`; then
- echo shar: \"'Cpp2.c'\" unpacked with wrong size!
- fi
- # end of 'Cpp2.c'
- fi
- if test -f 'Cpp3.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Cpp3.c'\"
- else
- echo shar: Extracting \"'Cpp3.c'\" \(14103 characters\)
- sed "s/^X//" >'Cpp3.c' <<'END_OF_FILE'
- X/*
- X * C P P 3 . C
- X *
- X * File open and command line options
- X *
- X * Edit history
- X * 13-Nov-84 MM Split from cpp1.c
- X * 21-Oct-85 rms Make -g command arg not cause an error.
- X * 14-Mar-86 FNF Incorporate macro based C debugging package.
- X * Port to the Commodore AMIGA.
- X * 20-Aug-88 Ois Added __TIME__, and changed __DATE__ to standard.
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <time.h> /*OIS*0.92*/
- X#include "cppdef.h"
- X#include "cpp.h"
- X#if DEBUG && (HOST == SYS_VMS || HOST == SYS_UNIX)
- X#include <signal.h>
- Xextern int abort(); /* For debugging */
- X#endif
- X
- Xint
- Xopenfile(filename)
- Xchar *filename;
- X/*
- X * Open a file, add it to the linked list of open files.
- X * This is called only from openfile() above.
- X */
- X{
- X register FILE *fp;
- X extern FILE *fopen ();
- X
- X DBUG_ENTER ("openfile");
- X if ((fp = fopen(filename, "r")) == NULL) {
- X#if DEBUG
- X perror(filename);
- X#endif
- X DBUG_RETURN (FALSE);
- X }
- X#if DEBUG
- X if (debug)
- X fprintf(stderr, "Reading from \"%s\"\n", filename);
- X#endif
- X addfile(fp, filename);
- X DBUG_RETURN (TRUE);
- X}
- X
- Xaddfile(fp, filename)
- XFILE *fp; /* Open file pointer */
- Xchar *filename; /* Name of the file */
- X/*
- X * Initialize tables for this open file. This is called from openfile()
- X * above (for #include files), and from the entry to cpp to open the main
- X * input file. It calls a common routine, getfile() to build the FILEINFO
- X * structure which is used to read characters. (getfile() is also called
- X * to setup a macro replacement.)
- X */
- X{
- X register FILEINFO *file;
- X extern FILEINFO *getfile();
- X
- X DBUG_ENTER ("addfile");
- X file = getfile(NBUFF, filename);
- X file->fp = fp; /* Better remember FILE * */
- X file->buffer[0] = EOS; /* Initialize for first read */
- X line = 1; /* Working on line 1 now */
- X wrongline = TRUE; /* Force out initial #line */
- X DBUG_VOID_RETURN;
- X}
- X
- Xsetincdirs()
- X/*
- X * Append system-specific directories to the include directory list.
- X * Called only when cpp is started.
- X */
- X{
- X
- X DBUG_ENTER ("setincdirs");
- X#ifdef CPP_INCLUDE
- X *incend++ = CPP_INCLUDE;
- X#define IS_INCLUDE 1
- X#else
- X#define IS_INCLUDE 0
- X#endif
- X
- X#if HOST == SYS_UNIX
- X *incend++ = "/usr/include";
- X#define MAXINCLUDE (NINCLUDE - 1 - IS_INCLUDE)
- X#endif
- X
- X#if HOST == SYS_AMIGADOS
- X *incend++ = "df0:include/"; /* These should be fixed. fnf */
- X *incend++ = "df1:include/";
- X#define MAXINCLUDE (NINCLUDE - 2 - IS_INCLUDE)
- X#endif
- X
- X#if HOST == SYS_VMS
- X extern char *getenv();
- X
- X if (getenv("C$LIBRARY") != NULL)
- X *incend++ = "C$LIBRARY:";
- X *incend++ = "SYS$LIBRARY:";
- X#define MAXINCLUDE (NINCLUDE - 2 - IS_INCLUDE)
- X#endif
- X
- X#if HOST == SYS_RSX
- X extern int $$rsts; /* TRUE on RSTS/E */
- X extern int $$pos; /* TRUE on PRO-350 P/OS */
- X extern int $$vms; /* TRUE on VMS compat. */
- X
- X if ($$pos) { /* P/OS? */
- X *incend++ = "SY:[ZZDECUSC]"; /* C #includes */
- X *incend++ = "LB:[1,5]"; /* RSX library */
- X }
- X else if ($$rsts) { /* RSTS/E? */
- X *incend++ = "SY:@"; /* User-defined account */
- X *incend++ = "C:"; /* Decus-C library */
- X *incend++ = "LB:[1,1]"; /* RSX library */
- X }
- X else if ($$vms) { /* VMS compatibility? */
- X *incend++ = "C:";
- X }
- X else { /* Plain old RSX/IAS */
- X *incend++ = "LB:[1,1]";
- X }
- X#define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE)
- X#endif
- X
- X#if HOST == SYS_RT11
- X extern int $$rsts; /* RSTS/E emulation? */
- X
- X if ($$rsts)
- X *incend++ = "SY:@"; /* User-defined account */
- X *incend++ = "C:"; /* Decus-C library disk */
- X *incend++ = "SY:"; /* System (boot) disk */
- X#define MAXINCLUDE (NINCLUDE - 3 - IS_INCLUDE)
- X#endif
- X DBUG_VOID_RETURN;
- X}
- X
- Xint
- Xdooptions(argc, argv)
- Xint argc;
- Xchar *argv[];
- X/*
- X * dooptions is called to process command line arguments (-Detc).
- X * It is called only at cpp startup.
- X */
- X{
- X register char *ap;
- X register DEFBUF *dp;
- X register int c;
- X int i, j;
- X char *arg;
- X SIZES *sizp; /* For -S */
- X int size; /* For -S */
- X int isdatum; /* FALSE for -S* */
- X int endtest; /* For -S */
- X
- X DBUG_ENTER ("dooptions");
- X for (i = j = 1; i < argc; i++) {
- X arg = ap = argv[i];
- X if (*ap++ != '-' || *ap == EOS)
- X argv[j++] = argv[i];
- X else {
- X c = *ap++; /* Option byte */
- X if (islower(c)) /* Normalize case */
- X c = toupper(c);
- X switch (c) { /* Command character */
- X case 'C': /* Keep comments */
- X cflag = TRUE;
- X keepcomments = TRUE;
- X break;
- X
- X case 'D': /* Define symbol */
- X#if HOST != SYS_UNIX && HOST != SYS_AMIGADOS
- X zap_uc(ap); /* Force define to U.C. */
- X#endif
- X /*
- X * If the option is just "-Dfoo", make it -Dfoo=1
- X */
- X while (*ap != EOS && *ap != '=')
- X ap++;
- X if (*ap == EOS)
- X ap = "1";
- X else
- X *ap++ = EOS;
- X /*
- X * Now, save the word and its definition.
- X */
- X dp = defendel(argv[i] + 2, FALSE);
- X dp->repl = savestring(ap);
- X dp->nargs = DEF_NOARGS;
- X break;
- X
- X case 'E': /* Ignore non-fatal */
- X eflag = TRUE; /* errors. */
- X break;
- X
- X case 'G': /* Cmpiler's debug switch */
- X break;
- X
- X case 'I': /* Include directory */
- X if (incend >= &incdir[MAXINCLUDE])
- X cfatal("Too many include directories", NULLST);
- X *incend++ = ap;
- X break;
- X
- X case 'N': /* No predefineds */
- X nflag++; /* Repeat to undefine */
- X break; /* __LINE__, etc. */
- X
- X#if OK_SIZEOF
- X case 'S':
- X sizp = size_table;
- X if (isdatum = (*ap != '*')) /* If it's just -S, */
- X endtest = T_FPTR; /* Stop here */
- X else { /* But if it's -S* */
- X ap++; /* Step over '*' */
- X endtest = 0; /* Stop at end marker */
- X }
- X while (sizp->bits != endtest && *ap != EOS) {
- X if (!isdigit(*ap)) { /* Skip to next digit */
- X ap++;
- X continue;
- X }
- X size = 0; /* Compile the value */
- X while (isdigit(*ap)) {
- X size *= 10;
- X size += (*ap++ - '0');
- X }
- X if (isdatum)
- X sizp->size = size; /* Datum size */
- X else
- X sizp->psize = size; /* Pointer size */
- X sizp++;
- X }
- X if (sizp->bits != endtest)
- X cwarn("-S, too few values specified in %s", argv[i]);
- X else if (*ap != EOS)
- X cwarn("-S, too many values, \"%s\" unused", ap);
- X break;
- X#endif /* OK_SIZEOF */
- X
- X case 'U': /* Undefine symbol */
- X#if HOST != SYS_UNIX && HOST != SYS_AMIGADOS
- X zap_uc(ap);
- X#endif
- X if (defendel(ap, TRUE) == NULL)
- X cwarn("\"%s\" wasn't defined", ap);
- X break;
- X case 'W':
- X wflag++;
- X break;
- X#if DEBUG
- X case 'X': /* Debug */
- X debug = (isdigit(*ap)) ? atoi(ap) : 1;
- X#if (HOST == SYS_VMS || HOST == SYS_UNIX)
- X signal(SIGINT, abort); /* Trap "interrupt" */
- X#endif
- X fprintf(stderr, "Debug set to %d\n", debug);
- X break;
- X#endif
- X
- X default: /* What is this one? */
- X cwarn("Unknown option \"%s\"", arg);
- Xfprintf(stderr, "The following options are valid:\n");
- Xfprintf(stderr, " -C\t\t\tWrite source file comments to output\n");
- Xfprintf(stderr, " -Dsymbol=value");
- Xfprintf(stderr, "\tDefine a symbol with the given (optional) value\n");
- Xfprintf(stderr, " -Idirectory");
- Xfprintf(stderr, "\t\tAdd a directory to the #include search list\n");
- Xfprintf(stderr, " -N\t\t\tDon't predefine target-specific names\n");
- Xfprintf(stderr, " -Stext\t\tSpecify sizes for #if sizeof\n");
- Xfprintf(stderr, " -Usymbol\t\tUndefine symbol\n");
- X#if DEBUG
- X fprintf(stderr, " -Xvalue\t\tSet internal debug flag\n");
- X#endif
- X break;
- X } /* Switch on all options */
- X } /* If it's a -option */
- X } /* For all arguments */
- X if (j > 3) {
- X cerror(
- X "Too many file arguments. Usage: cpp [input [output]]",
- X NULLST);
- X }
- X DBUG_RETURN (j); /* Return new argc */
- X}
- X
- X#if HOST != SYS_UNIX && HOST != SYS_AMIGADOS
- XFILE_LOCAL
- Xzap_uc(ap)
- Xregister char *ap;
- X/*
- X * Dec operating systems mangle upper-lower case in command lines.
- X * This routine forces the -D and -U arguments to uppercase.
- X * It is called only on cpp startup by dooptions().
- X */
- X{
- X DBUG_ENTER ("zap_uc");
- X while (*ap != EOS) {
- X /*
- X * Don't use islower() here so it works with Multinational
- X */
- X if (*ap >= 'a' && *ap <= 'z')
- X *ap = toupper(*ap);
- X ap++;
- X }
- X DBUG_VOID_RETURN;
- X}
- X#endif
- X
- Xinitdefines()
- X/*
- X * Initialize the built-in #define's. There are two flavors:
- X * #define decus 1 (static definitions)
- X * #define __FILE__ ?? (dynamic, evaluated by magic)
- X * Called only on cpp startup.
- X *
- X * Note: the built-in static definitions are supressed by the -N option.
- X * __LINE__, __FILE__, __TIME__ and __DATE__ are always present.
- X */
- X{
- X register char **pp;
- X register char *tp;
- X register DEFBUF *dp;
- X register struct tm *tm, *localtime();
- X int i;
- X long tvec;
- X
- X static char months[12][4] = {
- X "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- X };
- X
- X DBUG_ENTER ("initdefines");
- X DBUG_2 ("defs", "initialize built in defines");
- X /*
- X * Predefine the built-in symbols. Allow the
- X * implementor to pre-define a symbol as "" to
- X * eliminate it.
- X */
- X if (nflag == 0) {
- X for (pp = preset; *pp != NULL; pp++) {
- X if (*pp[0] != EOS) {
- X dp = defendel(*pp, FALSE);
- X dp->repl = savestring("1");
- X dp->nargs = DEF_NOARGS;
- X }
- X }
- X }
- X /*
- X * The magic pre-defines (__FILE__ and __LINE__ are
- X * initialized with negative argument counts. expand()
- X * notices this and calls the appropriate routine.
- X * DEF_NOARGS is one greater than the first "magic" definition.
- X */
- X if (nflag < 2) {
- X for (pp = magic, i = DEF_NOARGS; *pp != NULL; pp++) {
- X dp = defendel(*pp, FALSE);
- X dp->nargs = --i;
- X }
- X#if OK_DATE
- X /*
- X * Define __DATE__ as today's date.
- X */
- X dp = defendel("__DATE__", FALSE);
- X dp->repl = tp = getmem(14);
- X dp->nargs = DEF_NOARGS;
- X time(&tvec);
- X tm = localtime(&tvec);
- X sprintf(tp, "\"%3s %2d %4d\"", /* "Aug 20 1988" */
- X months[tm->tm_mon],
- X tm->tm_mday,
- X tm->tm_year + 1900);
- X
- X /*
- X * Define __TIME__ as this moment's time.
- X */
- X dp = defendel("__TIME__", FALSE);
- X dp->repl = tp = getmem(11);
- X dp->nargs = DEF_NOARGS;
- X sprintf(tp, "\"%2d:%02d:%02d\"", /* "20:42:31" */
- X tm->tm_hour,
- X tm->tm_min,
- X tm->tm_sec);
- X#endif
- X }
- X DBUG_VOID_RETURN;
- X}
- X
- Xdeldefines()
- X/*
- X * Delete the built-in #define's.
- X */
- X{
- X register char **pp;
- X int i;
- X
- X
- X DBUG_ENTER ("deldefines");
- X DBUG_2 ("deldefs", "delete built in defines");
- X /*
- X * Delete the built-in symbols, unless -WW.
- X */
- X if (wflag < 2) {
- X for (pp = preset; *pp != NULL; pp++) {
- X defendel(*pp, TRUE);
- X }
- X }
- X /*
- X * The magic pre-defines __FILE__ and __LINE__
- X */
- X for (pp = magic, i = DEF_NOARGS; *pp != NULL; pp++) {
- X defendel(*pp, TRUE);
- X }
- X#if OK_DATE
- X /*
- X * Undefine __DATE__.
- X */
- X defendel("__DATE__", TRUE);
- X
- X /*
- X * Undefine __TIME__.
- X */
- X defendel("__TIME__", TRUE);
- X#endif
- X DBUG_VOID_RETURN;
- X}
- X
- X#if HOST == SYS_VMS
- X/*
- X * getredirection() is intended to aid in porting C programs
- X * to VMS (Vax-11 C) which does not support '>' and '<'
- X * I/O redirection. With suitable modification, it may
- X * useful for other portability problems as well.
- X */
- X
- Xint
- Xgetredirection(argc, argv)
- Xint argc;
- Xchar **argv;
- X/*
- X * Process vms redirection arg's. Exit if any error is seen.
- X * If getredirection() processes an argument, it is erased
- X * from the vector. getredirection() returns a new argc value.
- X *
- X * Warning: do not try to simplify the code for vms. The code
- X * presupposes that getredirection() is called before any data is
- X * read from stdin or written to stdout.
- X *
- X * Normal usage is as follows:
- X *
- X * main(argc, argv)
- X * int argc;
- X * char *argv[];
- X * {
- X * argc = getredirection(argc, argv);
- X * }
- X */
- X{
- X register char *ap; /* Argument pointer */
- X int i; /* argv[] index */
- X int j; /* Output index */
- X int file; /* File_descriptor */
- X extern int errno; /* Last vms i/o error */
- X
- X DBUG_ENTER ("getredirection");
- X for (j = i = 1; i < argc; i++) { /* Do all arguments */
- X switch (*(ap = argv[i])) {
- X case '<': /* <file */
- X if (freopen(++ap, "r", stdin) == NULL) {
- X perror(ap); /* Can't find file */
- X exit(errno); /* Is a fatal error */
- X }
- X break;
- X
- X case '>': /* >file or >>file */
- X if (*++ap == '>') { /* >>file */
- X /*
- X * If the file exists, and is writable by us,
- X * call freopen to append to the file (using the
- X * file's current attributes). Otherwise, create
- X * a new file with "vanilla" attributes as if the
- X * argument was given as ">filename".
- X * access(name, 2) returns zero if we can write on
- X * the specified file.
- X */
- X if (access(++ap, 2) == 0) {
- X if (freopen(ap, "a", stdout) != NULL)
- X break; /* Exit case statement */
- X perror(ap); /* Error, can't append */
- X exit(errno); /* After access test */
- X } /* If file accessable */
- X }
- X /*
- X * On vms, we want to create the file using "standard"
- X * record attributes. creat(...) creates the file
- X * using the caller's default protection mask and
- X * "variable length, implied carriage return"
- X * attributes. dup2() associates the file with stdout.
- X */
- X if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1
- X || dup2(file, fileno(stdout)) == -1) {
- X perror(ap); /* Can't create file */
- X exit(errno); /* is a fatal error */
- X } /* If '>' creation */
- X break; /* Exit case test */
- X
- X default:
- X argv[j++] = ap; /* Not a redirector */
- X break; /* Exit case test */
- X }
- X } /* For all arguments */
- X argv[j] = NULL; /* Terminate argv[] */
- X DBUG_RETURN (j); /* Return new argc */
- X}
- X#endif
- X
- X
- END_OF_FILE
- if test 14103 -ne `wc -c <'Cpp3.c'`; then
- echo shar: \"'Cpp3.c'\" unpacked with wrong size!
- fi
- # end of 'Cpp3.c'
- fi
- if test -f 'org/cpp.mem' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'org/cpp.mem'\"
- else
- echo shar: Extracting \"'org/cpp.mem'\" \(12104 characters\)
- sed "s/^X//" >'org/cpp.mem' <<'END_OF_FILE'
- X
- X
- X
- X
- X 1.0 C Pre-Processor
- X
- X
- X
- X *******
- X * cpp *
- X *******
- X
- X
- X
- X NAME: cpp -- C Pre-Processor
- X
- X SYNOPSIS:
- X
- X cpp [-options] [infile [outfile]]
- X
- X DESCRIPTION:
- X
- X CPP reads a C source file, expands macros and include
- X files, and writes an input file for the C compiler. If
- X no file arguments are given, CPP reads from stdin and
- X writes to stdout. If one file argument is given, it
- X will define the input file, while two file arguments
- X define both input and output files. The file name "-"
- X is a synonym for stdin or stdout as appropriate.
- X
- X The following options are supported. Options may be
- X given in either case.
- X
- X -C If set, source-file comments are written
- X to the output file. This allows the
- X output of CPP to be used as the input to
- X a program, such as lint, that expects
- X commands embedded in specially-formatted
- X comments.
- X
- X -Dname=value Define the name as if the programmer
- X wrote
- X
- X #define name value
- X
- X at the start of the first file. If
- X "=value" is not given, a value of "1"
- X will be used.
- X
- X On non-unix systems, all alphabetic text
- X will be forced to upper-case.
- X
- X -E Always return "success" to the operating
- X system, even if errors were detected.
- X Note that some fatal errors, such as a
- X missing #include file, will terminate
- X CPP, returning "failure" even if the -E
- X option is given.
- X Page 2
- X cpp C Pre-Processor
- X
- X
- X -Idirectory Add this directory to the list of
- X directories searched for #include "..."
- X and #include <...> commands. Note that
- X there is no space between the "-I" and
- X the directory string. More than one -I
- X command is permitted. On non-Unix
- X systems "directory" is forced to
- X upper-case.
- X
- X -N CPP normally predefines some symbols
- X defining the target computer and
- X operating system. If -N is specified,
- X no symbols will be predefined. If -N -N
- X is specified, the "always present"
- X symbols, __LINE__, __FILE__, and
- X __DATE__ are not defined.
- X
- X -Stext CPP normally assumes that the size of
- X the target computer's basic variable
- X types is the same as the size of these
- X types of the host computer. (This can
- X be overridden when CPP is compiled,
- X however.) The -S option allows dynamic
- X respecification of these values. "text"
- X is a string of numbers, separated by
- X commas, that specifies correct sizes.
- X The sizes must be specified in the exact
- X order:
- X
- X char short int long float double
- X
- X If you specify the option as "-S*text",
- X pointers to these types will be
- X specified. -S* takes one additional
- X argument for pointer to function (e.g.
- X int (*)())
- X
- X For example, to specify sizes
- X appropriate for a PDP-11, you would
- X write:
- X
- X c s i l f d func
- X -S1,2,2,2,4,8,
- X -S*2,2,2,2,2,2,2
- X
- X Note that all values must be specified.
- X
- X -Uname Undefine the name as if
- X
- X #undef name
- X
- X were given. On non-Unix systems, "name"
- X will be forced to upper-case.
- X Page 3
- X cpp C Pre-Processor
- X
- X
- X -Xnumber Enable debugging code. If no value is
- X given, a value of 1 will be used. (For
- X maintenence of CPP only.)
- X
- X
- X PRE-DEFINED VARIABLES:
- X
- X When CPP begins processing, the following variables will
- X have been defined (unless the -N option is specified):
- X
- X Target computer (as appropriate):
- X
- X pdp11, vax, M68000 m68000 m68k
- X
- X Target operating system (as appropriate):
- X
- X rsx, rt11, vms, unix
- X
- X Target compiler (as appropriate):
- X
- X decus, vax11c
- X
- X The implementor may add definitions to this list. The
- X default definitions match the definition of the host
- X computer, operating system, and C compiler.
- X
- X The following are always available unless undefined (or
- X -N was specified twice):
- X
- X __FILE__ The input (or #include) file being
- X compiled (as a quoted string).
- X
- X __LINE__ The line number being compiled.
- X
- X __DATE__ The date and time of compilation as a
- X Unix ctime quoted string (the trailing
- X newline is removed). Thus,
- X
- X printf("Bug at line %s,", __LINE__);
- X printf(" source file %s", __FILE__);
- X printf(" compiled on %s", __DATE__);
- X
- X
- X DRAFT PROPOSED ANSI STANDARD CONSIDERATIONS:
- X
- X The current version of the Draft Proposed Standard
- X explicitly states that "readers are requested not to
- X specify or claim conformance to this draft." Readers and
- X users of Decus CPP should not assume that Decus CPP
- X conforms to the standard, or that it will conform to the
- X actual C Language Standard.
- X
- X When CPP is itself compiled, many features of the Draft
- X Proposed Standard that are incompatible with existing
- X Page 4
- X cpp C Pre-Processor
- X
- X
- X preprocessors may be disabled. See the comments in
- X CPP's source for details.
- X
- X The latest version of the Draft Proposed Standard (as
- X reflected in Decus CPP) is dated November 12, 1984.
- X
- X Comments are removed from the input text. The comment
- X is replaced by a single space character. The -C option
- X preserves comments, writing them to the output file.
- X
- X The '$' character is considered to be a letter. This is
- X a permitted extension.
- X
- X The following new features of C are processed by CPP:
- X
- X #elif expression (#else #if)
- X '\xNNN' (Hexadecimal constant)
- X '\a' (Ascii BELL)
- X '\v' (Ascii Vertical Tab)
- X #if defined NAME 1 if defined, 0 if not
- X #if defined (NAME) 1 if defined, 0 if not
- X #if sizeof (basic type)
- X unary +
- X 123U, 123LU Unsigned ints and longs.
- X 12.3L Long double numbers
- X token#token Token concatenation
- X #include token Expands to filename
- X
- X The Draft Proposed Standard has extended C, adding a
- X constant string concatenation operator, where
- X
- X "foo" "bar"
- X
- X is regarded as the single string "foobar". (This does
- X not affect CPP's processing but does permit a limited
- X form of macro argument substitution into strings as will
- X be discussed.)
- X
- X The Standard Committee plans to add token concatenation
- X to #define command lines. One suggested implementation
- X is as follows: the sequence "Token1#Token2" is treated
- X as if the programmer wrote "Token1Token2". This could
- X be used as follows:
- X
- X #line 123
- X #define ATLINE foo#__LINE__
- X
- X ATLINE would be defined as foo123.
- X
- X Note that "Token2" must either have the format of an
- X identifier or be a string of digits. Thus, the string
- X
- X #define ATLINE foo#1x3
- X Page 5
- X cpp C Pre-Processor
- X
- X
- X generates two tokens: "foo1" and "x3".
- X
- X If the tokens T1 and T2 are concatenated into T3, this
- X implementation operates as follows:
- X
- X 1. Expand T1 if it is a macro.
- X 2. Expand T2 if it is a macro.
- X 3. Join the tokens, forming T3.
- X 4. Expand T3 if it is a macro.
- X
- X A macro formal parameter will be substituted into a
- X string or character constant if it is the only component
- X of that constant:
- X
- X #define VECSIZE 123
- X #define vprint(name, size) \
- X printf("name" "[" "size" "] = {\n")
- X ... vprint(vector, VECSIZE);
- X
- X expands (effectively) to
- X
- X vprint("vector[123] = {\n");
- X
- X Note that this will be useful if your C compiler
- X supports the new string concatenation operation noted
- X above. As implemented here, if you write
- X
- X #define string(arg) "arg"
- X ... string("foo") ...
- X
- X This implementation generates "foo", rather than the
- X strictly correct ""foo"" (which will probably generate
- X an error message). This is, strictly speaking, an error
- X in CPP and may be removed from future releases.
- X
- X ERROR MESSAGES:
- X
- X Many. CPP prints warning or error messages if you try
- X to use multiple-byte character constants
- X (non-transportable) if you #undef a symbol that was not
- X defined, or if your program has potentially nested
- X comments.
- X
- X AUTHOR:
- X
- X Martin Minow
- X
- X BUGS:
- X
- X The #if expression processor uses signed integers only.
- X I.e, #if 0xFFFFu < 0 may be TRUE.
- X
- END_OF_FILE
- if test 12104 -ne `wc -c <'org/cpp.mem'`; then
- echo shar: \"'org/cpp.mem'\" unpacked with wrong size!
- fi
- # end of 'org/cpp.mem'
- fi
- echo shar: End of archive 2 \(of 5\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 4 5 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 5 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
- amiga@cs.odu.edu
- or amiga@xanth.cs.odu.edu ( obsolescent mailers may need this address )
- or ...!uunet!xanth!amiga ( very obsolescent mailers need this address )
-
- Comments, questions, and suggestions s should be addressed to ``amiga-request''
- (only use ``amiga'' for submissions) at the above addresses.
-